From d18cda81eb71b094fc31c5a1e271d1fecc188d7e Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 8 Jul 2004 12:00:59 +0000 Subject: [PATCH] bitkeeper revision 1.1051 (40ed377bW0cMKaeeMSXfQOknw3iMaw) Documentation. --- tools/python/xen/xend/server/blkif.py | 108 ++++++++++--- tools/python/xen/xend/server/channel.py | 26 +++- tools/python/xen/xend/server/controller.py | 169 ++++++++++++++------- 3 files changed, 224 insertions(+), 79 deletions(-) diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index 5596ddb842..bf51640ee1 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -29,8 +29,12 @@ class BlkifControllerFactory(controller.ControllerFactory): def createInstance(self, dom, recreate=0): """Create a block device controller for a domain. - dom domain - recreate if true it's a recreate (after xend restart) + @param dom: domain + @type dom: int + @param recreate: if true it's a recreate (after xend restart) + @type recreate: bool + @return: deferred + @rtype: twisted.internet.defer.Deferred """ d = defer.Deferred() blkif = self.getInstanceByDom(dom) @@ -51,9 +55,10 @@ class BlkifControllerFactory(controller.ControllerFactory): def getDomainDevices(self, dom): """Get the block devices for a domain. - dom domain - - returns devices + @param dom: domain + @type dom: int + @return: devices + @rtype: [device] """ blkif = self.getInstanceByDom(dom) return (blkif and blkif.getDevices()) or [] @@ -61,10 +66,12 @@ class BlkifControllerFactory(controller.ControllerFactory): def getDomainDevice(self, dom, vdev): """Get a block device from a domain. - dom domain - vdev device index - - returns device + @param dom: domain + @type dom: int + @param vdev: device index + @type vedv: int + @return: device + @rtype: device """ blkif = self.getInstanceByDom(dom) return (blkif and blkif.getDevice(vdev)) or None @@ -72,8 +79,10 @@ class BlkifControllerFactory(controller.ControllerFactory): def setControlDomain(self, dom, recreate=0): """Set the back-end block device controller domain. - dom domain - recreate if true it's a recreate (after xend restart) + @param dom: domain + @type dom: int + @param recreate: if true it's a recreate (after xend restart) + @type recreate: int """ if self.dom == dom: return self.deregisterChannel() @@ -84,14 +93,19 @@ class BlkifControllerFactory(controller.ControllerFactory): def getControlDomain(self): """Get the back-end block device controller domain. + + @return: domain + @rtype: int """ return self.dom def reattachDevice(self, dom, vdev): """Reattach a device (on changing control domain). - dom domain - vdev device index + @param dom: domain + @type dom: int + @param vdev: device index + @type vdev: int """ blkif = self.getInstanceByDom(dom) if blkif: @@ -102,6 +116,9 @@ class BlkifControllerFactory(controller.ControllerFactory): def devicesAttached(self): """Check if all devices are attached. + + @return: true if all devices attached + @rtype: bool """ attached = 1 for blkif in self.getInstances(): @@ -111,19 +128,32 @@ class BlkifControllerFactory(controller.ControllerFactory): return attached def reattached(self): - """Notify all block interface we have been reattached + """Notify all block interfaces we have been reattached (after changing control domain). """ for blkif in self.getInstances(): blkif.reattached() def respond_be_create(self, msg, d): + """Response handler for a be_create message. + Calls I{d} with the block interface created. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred + """ print 'respond_be_create>' val = unpackMsg('blkif_be_create_t', msg) blkif = self.getInstanceByDom(val['domid']) d.callback(blkif) def respond_be_connect(self, msg): + """Response handler for a be_connect message. + + @param msg: message + @type msg: xu message + """ print 'respond_be_connect>', self val = unpackMsg('blkif_be_connect_t', msg) blkif = self.getInstanceByDom(val['domid']) @@ -133,6 +163,15 @@ class BlkifControllerFactory(controller.ControllerFactory): pass def respond_be_vbd_create(self, msg, d): + """Response handler for a be_vbd_create message. + Tries to grow the vbd, and passes the deferred I{d} on for + the grow to call. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred + """ print 'recv_be_vbd_create>', self val = unpackMsg('blkif_be_vbd_create_t', msg) blkif = self.getInstanceByDom(val['domid']) @@ -145,6 +184,13 @@ class BlkifControllerFactory(controller.ControllerFactory): pass def respond_be_vbd_grow(self, msg, d): + """Response handler for a be_vbd_grow message. + + @param msg: message + @type msg: xu message + @param d: deferred to call + @type d: Deferred or None + """ print 'recv_be_vbd_grow>', self val = unpackMsg('blkif_be_vbd_grow_t', msg) # Check status? @@ -155,6 +201,13 @@ class BlkifControllerFactory(controller.ControllerFactory): self.reattachDevice(val['domid'], val['vdevice']) def recv_be_driver_status_changed(self, msg, req): + """Request handler for be_driver_status_changed messages. + + @param msg: message + @type msg: xu message + @param req: request flag (true if the msg is a request) + @type req: bool + """ print 'recv_be_driver_status_changed>', self, req val = unpackMsg('blkif_be_driver_status_changed_t', msg) status = val['status'] @@ -222,6 +275,17 @@ class BlkifController(controller.Controller): return self.devices.get(vdev) def addDevice(self, vdev, mode, segment): + """Add a device to the device table. + + @param vdev: device index + @type vdev: int + @param mode: read/write mode + @type mode: string + @param segment: segment + @type segment: int + @return: device + @rtype: BlkDev + """ if vdev in self.devices: return None dev = BlkDev(self, vdev, mode, segment) self.devices[vdev] = dev @@ -230,12 +294,16 @@ class BlkifController(controller.Controller): def attachDevice(self, vdev, mode, segment, recreate=0): """Attach a device to the specified interface. - vdev device index - mode read/write mode - segment segment - recreate if true it's being recreated (after xend restart) - - returns deferred + @param vdev: device index + @type vdev: int + @param mode: read/write mode + @type mode: string + @param segment: segment + @type segment: int + @param recreate: if true it's being recreated (after xend restart) + @type recreate: bool + @return: deferred + @rtype: Deferred """ dev = self.addDevice(vdev, mode, segment) if not dev: return -1 diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py index caaa66e28c..d78ba252cb 100755 --- a/tools/python/xen/xend/server/channel.py +++ b/tools/python/xen/xend/server/channel.py @@ -2,7 +2,7 @@ import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() from xen.lowlevel import xu -from messages import msgTypeName +from messages import msgTypeName, printMsg VIRQ_MISDIRECT = 0 # Catch-all interrupt for unbound VIRQs. VIRQ_TIMER = 1 # Timebase update, and/or requested timeout. @@ -222,12 +222,18 @@ class Channel(BaseChannel): def getLocalPort(self): """Get the local port. + + @return: local port + @rtype: int """ if self.closed: return -1 return self.port.local_port def getRemotePort(self): """Get the remote port. + + @return: remote port + @rtype: int """ if self.closed: return -1 return self.port.remote_port @@ -248,8 +254,9 @@ class Channel(BaseChannel): def registerDevice(self, types, dev): """Register a device controller. - @param types message types the controller handles - @param dev device controller + @param types: message types the controller handles + @type types: array of ints + @param dev: device controller """ if self.closed: return self.devs.append(dev) @@ -259,7 +266,7 @@ class Channel(BaseChannel): def deregisterDevice(self, dev): """Remove the registration for a device controller. - @param dev device controller + @param dev: device controller """ if dev in self.devs: self.devs.remove(dev) @@ -270,13 +277,20 @@ class Channel(BaseChannel): def getDevice(self, type): """Get the device controller handling a message type. - @param type message type - @returns controller or None + @param type: message type + @type type: int + @return: controller or None + @rtype: device controller """ return self.devs_by_type.get(type) def getMessageType(self, msg): """Get a 2-tuple of the message type and subtype. + + @param msg: message + @type msg: xu message + @return: type info + @rtype: (int, int) """ hdr = msg.get_header() return (hdr['type'], hdr.get('subtype')) diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index 6d0bd9295f..a9f416908a 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -1,53 +1,80 @@ # Copyright (C) 2004 Mike Wray +"""General support for controllers, which handle devices +for a domain. +""" from twisted.internet import defer defer.Deferred.debug = 1 import channel -from messages import msgTypeName +from messages import msgTypeName, printMsg -DEBUG=0 +DEBUG = 0 class OutOfOrderError(RuntimeError): - """Error reported when a response arrives out of order. + """Error reported when a response message arrives out of order. """ pass class Responder: - """Handler for a response to a message. + """Handler for a response to a message with a specified id. """ def __init__(self, mid, deferred): """Create a responder. - mid message id of response to handle - deferred deferred object holding the callbacks + @param mid: message id of response to handle + @type mid: int + @param deferred: deferred object holding the callbacks + @type deferred: Deferred """ self.mid = mid self.deferred = deferred def responseReceived(self, msg): + """Entry point called when a response message with the right id arrives. + Calls callback on I{self.deferred} with the message. + + @param msg: response message + @type msg: xu message + """ if self.deferred.called: return self.deferred.callback(msg) def error(self, err): + """Entry point called when there has been an error. + Calls errback on I{self.deferred} with the error. + + @param err: error + @type err: Exception + """ if self.deferred.called: return self.deferred.errback(err) class CtrlMsgRcvr: """Abstract class for things that deal with a control interface to a domain. - - Instance variables: - - dom : the domain we are a control interface for - majorTypes: list of major message types we are interested in - subTypes : mapping of message subtypes to methods + Once I{registerChannel} has been called, our message types are registered + with the channel to the domain. The channel will call I{requestReceived} + when a request arrives, or I{responseReceived} when a response arrives, + if they have one of our message types. + + @ivar dom: the domain we are a control interface for + @type dom: int + @ivar majorTypes: major message types we are interested in + @type majorTypes: [int] + @ivar subTypes: mapping of message subtypes to methods + @ivar subTypes: {int:method} + @ivar timeout: timeout (in seconds) for message handlers + @type timeout: int - channel : channel to the domain - idx : channel index + @ivar channel: channel to the domain + @type channel: Channel + @ivar idx: channel index + @ivar idx: string + @ivar responders: table of message response handlers + @type responders: {int:Responder} """ - def __init__(self): self.channelFactory = channel.channelFactory() self.majorTypes = [ ] @@ -56,22 +83,25 @@ class CtrlMsgRcvr: self.channel = None self.idx = None self.responders = [] - # Timeout (in seconds) for deferreds. self.timeout = 10 def setTimeout(self, timeout): self.timeout = timeout def requestReceived(self, msg, type, subtype): - """Dispatch a request to handlers. - - msg message - type major message type - subtype minor message type + """Dispatch a request message to handlers. + Called by the channel for requests with one of our types. + + @param msg: message + @type msg: xu message + @param type: major message type + @type type: int + @param subtype: minor message type + @type subtype: int """ - msgid = msg.get_header()['id'] if DEBUG: - print 'requestReceived>', self, msgid, msgTypeName(type, subtype) + print 'requestReceived>', + printMsg(msg, all=1) method = self.subTypes.get(subtype) if method: method(msg, 1) @@ -81,14 +111,23 @@ class CtrlMsgRcvr: def responseReceived(self, msg, type, subtype): """Dispatch a response to handlers. - - msg message - type major message type - subtype minor message type + Called by the channel for responses with one of our types. + + First looks for a message responder for the message's id. + See L{callResponders}, L{addResponder}. + If there is no responder, looks for a message handler for + the message type/subtype. + + @param msg: message + @type msg: xu message + @param type: major message type + @type type: int + @param subtype: minor message type + @type subtype: int """ - msgid = msg.get_header()['id'] if DEBUG: - print 'responseReceived>', self, msgid, msgTypeName(type, subtype) + print 'responseReceived>', + printMsg(msg, all=1) if self.callResponders(msg): return method = self.subTypes.get(subtype) @@ -100,16 +139,21 @@ class CtrlMsgRcvr: def addResponder(self, mid, deferred): """Add a responder for a message id. - The deferred is called with callback(msg) when a response - with the given message id arrives. Responses are expected + The I{deferred} is called with callback(msg) when a response + with message id I{mid} arrives. Responses are expected to arrive in order of message id. When a response arrives, waiting responders for messages with lower id have errback called with an OutOfOrder error. - mid message id of response expected - deferred a Deferred to handle the response + Responders have a timeout set and I{deferred} will error + on expiry. - returns Responder + @param mid: message id of response expected + @type mid: int + @param deferred: handler for the response + @type deferred: Deferred + @return: responder + @rtype: Responder """ if self.timeout > 0: deferred.setTimeout(self.timeout) @@ -119,10 +163,13 @@ class CtrlMsgRcvr: def callResponders(self, msg): """Call any waiting responders for a response message. + Looks for a responder registered for the message's id. + See L{addResponder}. - msg response message - - returns 1 if there was a responder for the message, 0 otherwise + @param msg: response message + @type msg: xu message + @return: 1 if there was a responder for the message, 0 otherwise + @rtype : bool """ hdr = msg.get_header() mid = hdr['id'] @@ -133,7 +180,7 @@ class CtrlMsgRcvr: break self.responders.pop() if resp.mid < mid: - print 'handleResponse> Out of order:', resp.mid, mid + print 'callResponders> Out of order:', resp.mid, mid resp.error(OutOfOrderError()) else: handled = 1 @@ -148,7 +195,8 @@ class CtrlMsgRcvr: def registerChannel(self): """Register interest in our major message types with the - channel to our domain. + channel to our domain. Once we have registered, the channel + will call requestReceived or responseReceived for our messages. """ self.channel = self.channelFactory.domChannel(self.dom) self.idx = self.channel.getIndex() @@ -157,7 +205,8 @@ class CtrlMsgRcvr: def deregisterChannel(self): """Deregister interest in our major message types with the - channel to our domain. + channel to our domain. After this the channel won't call + us any more. """ if self.channel: self.channel.deregisterDevice(self) @@ -166,18 +215,23 @@ class CtrlMsgRcvr: def produceRequests(self): """Produce any queued requests. - return number produced + @return: number produced + @rtype: int """ return 0 def writeRequest(self, msg, response=None): """Write a request to the channel. - msg message - response Deferred to handle the response (optional) + @param msg: request message + @type msg: xu message + @param response: response handler + @type response: Deferred """ if self.channel: - if DEBUG: print 'CtrlMsgRcvr>writeRequest>', self, msg + if DEBUG: + print 'CtrlMsgRcvr>writeRequest>', + printMsg(msg, all=1) if response: self.addResponder(msg.get_header()['id'], response) self.channel.writeRequest(msg) @@ -185,29 +239,33 @@ class CtrlMsgRcvr: print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self def writeResponse(self, msg): - """Write a response to the channel. + """Write a response to the channel. This acknowledges + a request message. + + @param msg: message + @type msg: xu message """ if self.channel: - if DEBUG: print 'CtrlMsgRcvr>writeResponse>', self, msg + if DEBUG: + print 'CtrlMsgRcvr>writeResponse>', + printMsg(msg, all=0) self.channel.writeResponse(msg) else: print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self class ControllerFactory(CtrlMsgRcvr): - """Abstract class for factories creating controllers. + """Abstract class for factories creating controllers for a domain. Maintains a table of instances. - Instance variables: - - instances : mapping of index to controller instance - dlist : list of deferreds - dom : domain + @ivar instances: mapping of index to controller instance + @type instances: {int: Controller} + @ivar dom: domain + @type dom: int """ def __init__(self): CtrlMsgRcvr.__init__(self) self.instances = {} - self.dlist = [] self.dom = 0 def addInstance(self, instance): @@ -241,6 +299,11 @@ class ControllerFactory(CtrlMsgRcvr): def createInstance(self, dom, recreate=0): """Create an instance. Define in a subclass. + + @param dom: domain + @type dom: int + @param recreate: true if the instance is being recreated (after xend restart) + @type recreate: int """ raise NotImplementedError() -- 2.30.2